using System;
using Coderoom.ScrumPlanner.Data;
using Coderoom.ScrumPlanner.Domain;
using Coderoom.ScrumPlanner.Tests.FakeRepositories;
using Xunit;

namespace Coderoom.ScrumPlanner.Tests.Unit.ServiceTests
{
	public class TaskServiceTests
	{
		private readonly TaskService _service;

		public TaskServiceTests()
		{
			var repository = new FakeTaskRepository();
			_service = new TaskService(repository);
		}

		[Fact]
		public void GetTasksByUserStoryId_returns_TaskCollection()
		{
			// arrange
			var userStoryId = new Guid("A5960D03-0648-4D17-BF55-8C0E86DDEC32");

			// act
			var tasks = _service.GetTasks(userStoryId);

			// assert
			Assert.NotNull(tasks);
			Assert.IsType<TaskCollection>(tasks);
			Assert.Equal(2, tasks.Count);

			Assert.Equal(new Guid("FDB854A9-9D52-414C-83DA-469DEAD2A0D8"), tasks[0].Id);
			Assert.Equal("Task A", tasks[0].Title);
			Assert.Equal("task-a", tasks[0].Slug);
			Assert.Equal(1, tasks[0].EstimatedComplexity);

			Assert.Equal(new Guid("B84EF056-321E-4ACE-855F-3DB1EC5C03F4"), tasks[1].Id);
			Assert.Equal("Task B", tasks[1].Title);
			Assert.Equal("task-b", tasks[1].Slug);
			Assert.Equal(2, tasks[1].EstimatedComplexity);
		}

		[Fact]
		public void GetTask_returns_Task_when_task_is_found()
		{
			// arrange
			var id = new Guid("B84EF056-321E-4ACE-855F-3DB1EC5C03F4");

			// act
			var task = _service.GetTask(id);

			// assert
			Assert.NotNull(task);
			Assert.IsType<Task>(task);
			Assert.Equal(new Guid("B84EF056-321E-4ACE-855F-3DB1EC5C03F4"), task.Id);
			Assert.Equal("Task B", task.Title);
			Assert.Equal("task-b", task.Slug);
			Assert.Equal(2, task.EstimatedComplexity);
		}

		[Fact]
		public void GetTask_returns_null_when_task_is_not_found()
		{
			// arrange
			var id = Guid.Empty;

			// act
			var task = _service.GetTask(id);

			// assert
			Assert.Null(task);
		}

		[Fact]
		public void CreateTask_returns_void_when_task_is_created()
		{
			// arrange
			var userStoryId = new Guid("A5960D03-0648-4D17-BF55-8C0E86DDEC32");
			var tasks = _service.GetTasks(userStoryId);
			Assert.Equal(2, tasks.Count);

			var newTask = new Task();
			newTask.Title = "Task C";
			newTask.Slug = "task-c";
			newTask.UserStoryId = userStoryId;
			newTask.EstimatedComplexity = 3;

			// act
			_service.CreateTask(newTask);

			// assert
			tasks = _service.GetTasks(userStoryId);

			Assert.Equal(3, tasks.Count);

			Assert.NotEqual(Guid.Empty, tasks[2].Id);
			Assert.Equal("Task C", tasks[2].Title);
			Assert.Equal("task-c", tasks[2].Slug);
			Assert.Equal(userStoryId, tasks[2].UserStoryId);
			Assert.Equal(3, tasks[2].EstimatedComplexity);
		}

		[Fact]
		public void CreateTask_throws_ArgumentNullException_when_task_with_null_title_is_passed()
		{
			// arrange
			var task = new Task();

			// act
			Assert.Throws<ArgumentException>(() => _service.CreateTask(task));
		}

		[Fact]
		public void CreateTask_throws_ArgumentException_when_task_with_empty_title_is_passed()
		{
			// arrange
			var task = new Task();
			task.Title = string.Empty;

			// act
			Assert.Throws<ArgumentException>(() => _service.CreateTask(task));
		}

		[Fact]
		public void DeleteTask_returns_true_when_task_is_deleted()
		{
			// arrange
			var userStoryId = new Guid("A5960D03-0648-4D17-BF55-8C0E86DDEC32");

			Assert.Equal(2, _service.GetTasks(userStoryId).Count);

			var id = _service.GetTasks(userStoryId)[1].Id;

			// act
			var result = _service.DeleteTask(id);

			// assert
			Assert.True(result);
			Assert.Equal(1, _service.GetTasks(userStoryId).Count);
		}

		[Fact]
		public void DeleteTask_returns_false_when_task_is_not_deleted()
		{
			// arrange
			var userStoryId = new Guid("A5960D03-0648-4D17-BF55-8C0E86DDEC32");

			Assert.Equal(2, _service.GetTasks(userStoryId).Count);

			var id = Guid.Empty;

			// act
			var result = _service.DeleteTask(id);

			// assert
			Assert.False(result);
			Assert.Equal(2, _service.GetTasks(userStoryId).Count);
		}
	}
}